package com.pcitc.smcc.vulnerability.common.handler;

import org.springframework.core.MethodParameter;
import org.springframework.http.MediaType;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.server.ServerHttpRequest;
import org.springframework.http.server.ServerHttpResponse;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import org.springframework.web.servlet.mvc.method.annotation.ResponseBodyAdvice;

import com.alibaba.fastjson.JSON;
import com.pcitc.smcc.vulnerability.entity.ResultWrapper;

/**
 * 全局统一接口返回类型配置
 * @author:张三石
 * @since:2020年3月30日 下午4:27:22
 */
@RestControllerAdvice
public class GlobalReturnValueHandler implements ResponseBodyAdvice<Object> {

	/**
	 * 该组件是否支持给定的控制器方法返回类型和所选的HttpMessageConverter类型。
	 * 不转换返回值为void的方法 
	 * @param returnType 返回值类型
	 * @param converterType 转换器类型
	 * @return boolean 是否转换返回类型
	 * @see org.springframework.web.servlet.mvc.method.annotation.ResponseBodyAdvice#supports(org.springframework.core.MethodParameter, java.lang.Class)
	 */
	@Override
	public boolean supports(MethodParameter returnType, Class<? extends HttpMessageConverter<?>> converterType) {
		// 过滤返回值为'void'的接口
		return !returnType.getMethod().getReturnType().isAssignableFrom(Void.TYPE);
	}

	/**
	 * 配置统一返回类型
	 * @return 转换后的类型
	 * @see org.springframework.web.servlet.mvc.method.annotation.ResponseBodyAdvice#beforeBodyWrite(java.lang.Object, org.springframework.core.MethodParameter, org.springframework.http.MediaType, java.lang.Class, org.springframework.http.server.ServerHttpRequest, org.springframework.http.server.ServerHttpResponse)
	 */
	@Override
	public Object beforeBodyWrite(Object body, MethodParameter returnType, MediaType selectedContentType, Class<? extends HttpMessageConverter<?>> selectedConverterType, ServerHttpRequest request,
			ServerHttpResponse response) {
		// 获取请求路径
		String path = request.getURI().getPath();
		/*
		 *  如果返回值已封装为Result类型或者为swagger的请求则原样返回，如果接口返回值为String类型则解析器为StringMessageConverter
		 *  解析时出现异常。解决该异常最好的方式就是重写StringMessageConverter方法,但是也可以用一下简单实现
		 */
		if (body instanceof ResultWrapper) {
			return body;
		} else if (path.contains("/swagger") || path.contains("/v3/api-docs") || path.contains("/v2/api-docs")) {
			return body;
		} else if (body instanceof String) {
			return JSON.toJSONString(new ResultWrapper<>(0, "操作成功", body));
		}
		return new ResultWrapper<>(0, "操作成功", body);
	}
}
